package com.sky.service.impl;

import com.sky.constant.MessageConstant;
import com.sky.dto.DataOverViewQueryDTO;
import com.sky.entity.*;
import com.sky.exception.BaseException;
import com.sky.mapper.BusinessDataMapper;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrdersMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.vo.OrderReportVO;
import com.sky.vo.SalesTop10ReportVO;
import com.sky.vo.TurnoverReportVO;
import com.sky.vo.UserReportVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private BusinessDataMapper businessDataMapper;

    /**
     * 营业额统计
     * @param dataOverViewQueryDTO
     * @return
     */
    @Override
    public TurnoverReportVO getTurnover(DataOverViewQueryDTO dataOverViewQueryDTO) {
        if (dataOverViewQueryDTO == null){
            throw new BaseException(MessageConstant.PARAM_ERROR);
        }
        List<LocalDate> dateList = createDateList(dataOverViewQueryDTO.getBegin(),dataOverViewQueryDTO.getEnd());
        dataOverViewQueryDTO.setStatus(Orders.COMPLETED);
        //查询日期和营业额,订单状态为已完成
        List<Turnover> dbList = ordersMapper.getTurnover(dataOverViewQueryDTO);
        //对日期集合做一个处理
        List<Double> turnoverList = dateList.stream().map(day -> {
            //先创建一个销量对象,分别设置日期和初始值0.0
            Turnover turnover = new Turnover();
            turnover.setDay(day);
            turnover.setTurnover(0.0);
            //遍历查到的集合,如果对应的日期有数据,就覆盖原来的数据
            if (dbList != null && dbList.size() > 0) {
                for (Turnover tr : dbList) {
                    if (tr.getDay().equals(day)) {
                        turnover.setTurnover(tr.getTurnover());
                        break;
                    }
                }
            }
            return turnover;
            //最终再将查到的销量数据做一个组成一个新的集合
        }).map(Turnover::getTurnover).collect(Collectors.toList());
        return TurnoverReportVO.builder()
                //将集合转成字符串,以逗号分隔
                .turnoverList(StringUtils.join(turnoverList,","))
                //将集合转成字符串,以逗号分隔
                .dateList(StringUtils.join(dateList,","))
                .build();
    }

    /**
     * 用户统计
     * @param dataOverViewQueryDTO
     * @return
     */
    @Override
    public UserReportVO getUser(DataOverViewQueryDTO dataOverViewQueryDTO) {
        //创建日期集合
        List<LocalDate> dateList = createDateList(dataOverViewQueryDTO.getBegin(),dataOverViewQueryDTO.getEnd());
        ArrayList<Integer> newUserList = new ArrayList<>();
        ArrayList<Integer> totalUserList = new ArrayList<>();
        dateList.forEach(day->{
            //查询每日新增用户
            Integer newUserCount = userMapper.countByCreateTime(day);
            newUserList.add(newUserCount);
            //查询总用户
            Integer totalUserCount = userMapper.totalByCreateTime(day);
            totalUserList.add(totalUserCount);
        });
        return UserReportVO.builder()
                .dateList(StringUtils.join(dateList,","))
                .newUserList(StringUtils.join(newUserList,","))
                .totalUserList(StringUtils.join(totalUserList,","))
                .build();
    }

    /**
     * 订单统计
     * @param dataOverViewQueryDTO
     * @return
     */
    @Override
    public OrderReportVO getOrders(DataOverViewQueryDTO dataOverViewQueryDTO) {
        //生成日期集合
        List<LocalDate> dateList = createDateList(dataOverViewQueryDTO.getBegin(),dataOverViewQueryDTO.getEnd());
        //根据下单时间查询日期和订单数量
        List<OrderCountInfo> dbOrderCountListCountInfo = ordersMapper.countByOrderTime(dataOverViewQueryDTO);
        dataOverViewQueryDTO.setStatus(Orders.COMPLETED);
        //根据下单时间查询已完成的订单的日期和数量
        List<OrderCompleteInfo> dbOrderCompleteInfoList = ordersMapper.countByOrderTimeAndStatus(dataOverViewQueryDTO);
        //整个stream流的过程是根据日期集合组装订单数量,最后再讲订单数量收集成集合
        List<Integer> orderCountList = dateList.stream().map(day -> {
            OrderCountInfo orderCountInfo = new OrderCountInfo();
            orderCountInfo.setDay(day);
            orderCountInfo.setOrderCount(0);
            if (dbOrderCountListCountInfo != null && dbOrderCountListCountInfo.size() > 0) {
                for (OrderCountInfo oc : dbOrderCountListCountInfo) {
                    if (oc.getDay().equals(day)) {
                        orderCountInfo.setOrderCount(oc.getOrderCount());
                        break;
                    }
                }
            }
            return orderCountInfo;
        }).map(OrderCountInfo::getOrderCount).collect(Collectors.toList());
        //整个stream流的过程是根据日期集合组装已经完成的订单数量,最后再讲订单数量收集成集合
        List<Integer> validOrderCountList = dateList.stream().map(day -> {
            OrderCompleteInfo orderCompleteInfo = new OrderCompleteInfo();
            orderCompleteInfo.setDay(day);
            orderCompleteInfo.setValidOrderCount(0);
            if (dbOrderCompleteInfoList != null && dbOrderCompleteInfoList.size() > 0) {
                for (OrderCompleteInfo dci : dbOrderCompleteInfoList) {
                    if (dci.getDay().equals(day)) {
                        orderCompleteInfo.setValidOrderCount(dci.getValidOrderCount());
                        break;
                    }
                }
            }
            return orderCompleteInfo;
        }).map(OrderCompleteInfo::getValidOrderCount).collect(Collectors.toList());
        //查询订单总数
        Integer totalOrderCount = ordersMapper.countOrders();
        //查询已完成的订单数
        Integer totalValidOrderCount = ordersMapper.countByStatus(Orders.COMPLETED);
        BigDecimal bd1 = new BigDecimal(totalOrderCount + "");
        BigDecimal bd2 = new BigDecimal(totalValidOrderCount + "");
        double orderCompletionRate = 1.0;
        //用BigDecimal做精确运算完成的订单总数 / 订单总数 = 完成率
        if (totalOrderCount != 0) {
            orderCompletionRate = bd2.divide(bd1, 2, RoundingMode.HALF_UP).doubleValue();
        }
        return OrderReportVO.builder()
                .dateList(StringUtils.join(dateList,","))
                .orderCompletionRate(orderCompletionRate)
                .orderCountList(StringUtils.join(orderCountList,","))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(totalValidOrderCount)
                .validOrderCountList(StringUtils.join(validOrderCountList,","))
                .build();
    }

    /**
     * 查询销量排名top10
     * @param dataOverViewQueryDTO
     * @return
     */
    @Override
    public SalesTop10ReportVO salesTop10(DataOverViewQueryDTO dataOverViewQueryDTO) {
        dataOverViewQueryDTO.setStatus(Orders.COMPLETED);
        //根据送达时间查询完成状态的订单id
        List<Long> orderIdList = ordersMapper.findByStatusAndDeliveryTime(dataOverViewQueryDTO);
        ArrayList<String> nameList = new ArrayList<>();
        ArrayList<Integer> numberList = new ArrayList<>();
        if (orderIdList != null && orderIdList.size() > 0) {
            //根据orderId查询菜品名字和销量,并且按销量排序
            List<SalesVolume> salesList = orderDetailMapper.findByOrderIds(orderIdList);
            //取销量前10名
            salesList = salesList.subList(0, Math.min(salesList.size(), 10));
            salesList.forEach(sales->{
                nameList.add(sales.getName());
                numberList.add(sales.getSales());
            });
        }
        return SalesTop10ReportVO.builder()
                .nameList(StringUtils.join(nameList,","))
                .numberList(StringUtils.join(numberList,","))
                .build();
    }

    /**
     * 导出订单
     * @return
     */
    @Override
    public List<BusinessData> export() {
        LocalDate end = LocalDate.now();
        LocalDate begin = end.minusDays(30);
        //查询近30天营业数据
        return businessDataMapper.findByDate(begin,end);
    }

    /**
     * 创建日期集合
     * @param begin
     * @param end
     * @return
     */
    private List<LocalDate> createDateList(LocalDate begin, LocalDate end) {
        ArrayList<LocalDate> dateList = new ArrayList<>();
        dateList.add(begin);
        while (!begin.equals(end)){
            begin = begin.plusDays(1);
            dateList.add(begin);
        }
        return dateList;
    }
}
